package service;

import model.*;
import route.NewTemplate;
import route.Route;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.UUID;

public class ServiceAuth {

    public static void log(String format, Object... args) {
        System.out.println(String.format(format, args));
    }


    public static String hexFromBytes(byte[] bytes) {
        StringBuilder result = new StringBuilder();
        for (int i = 0, bytesLength = bytes.length; i < bytesLength; i++) {
            byte currentByte = bytes[i];
            // 02 代表不足两位补足两位 x代表用16进制表示
            // String.format("%02x", 0) = "00"
            result.append(String.format("%02x", currentByte));
        }
        return result.toString();
    }

    public static String SaltedPasswordHash(String password, String salt) {
        MessageDigest md;
        try {
            md = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        String salted = salt + password;
        md.update(salted.getBytes(StandardCharsets.UTF_8));
        byte[] result = md.digest();
        return hexFromBytes(result);
    }

    public static String login(String username, String password) {
        String sql = "SELECT * FROM `blog`.`user`";
        ArrayList<User> users = MySQLStorage.select(
                sql,
                resultSet -> {
                    int id = resultSet.getInt("id");
                    String usernameSql = resultSet.getString("username");
                    String passwordSql = resultSet.getString("password");
                    String role = resultSet.getString("role");
                    String salt = resultSet.getString("salt");
                    return new User(id, usernameSql, passwordSql, UserRole.valueOf(role), salt);
                }
        );
        for (int i = 0; i < users.size(); i++) {
            User currentUser = users.get(i);
            if (currentUser.username.equals(username)) {
                String salt = currentUser.salt;
                String saltedPassword = ServiceAuth.SaltedPasswordHash(password, salt);
                if (currentUser.password.equals(saltedPassword)) {
                    // cookie = String.format("Set-Cookie: username=%s\r\n", currentUser.username);
                    String sessionId = UUID.randomUUID().toString();
                    // 将 session 存入数据库
                    String sql1 = "INSERT INTO `blog`.`session` (sessionId, username) VALUES (?, ?)";
                    MySQLStorage.update(sql1, statement -> {
                        statement.setString(1, sessionId);
                        statement.setString(2, username);
                    });
                    return sessionId;
                }
            }
        }
        return "";
    }

    public static User guest() {
        User user = new User(0, "游客", "dadasds", UserRole.guest, "dasdas");
        return user;
    }

    /**
     * 遍历session，拿到当前用户名
     *
     * @param id
     * @return
     */
    public static String usernameFromSessionId(String id) {
        String sql = "SELECT * FROM `blog`.`session` WHERE sessionId = ?";
        ArrayList<Session> sessions = MySQLStorage.select(
                sql,
                resultSet -> {
                    String sessionId = resultSet.getString("sessionId");
                    String username = resultSet.getString("username");
                    return new Session(sessionId, username);
                },
                statement -> {
                    statement.setString(1, id);
                }
        );
        if (sessions.size() > 0) {
            Session session = sessions.get(0);
            return session.username;
        } else {
            return guest().username;
        }
    }

    /**
     * 得到当前用户信息
     *
     * @param username
     * @return
     */
    public static User userFromUsername(String username) {
        String sql = "SELECT * FROM `blog`.`user`";
        ArrayList<User> users = MySQLStorage.select(
                sql,
                resultSet -> {
                    int id = resultSet.getInt("id");
                    String usernameSql = resultSet.getString("username");
                    String passwordSql = resultSet.getString("password");
                    String role = resultSet.getString("role");
                    String salt = resultSet.getString("salt");
                    return new User(id, usernameSql, passwordSql, UserRole.valueOf(role), salt);
                }
        );
        for (int i = 0; i < users.size(); i++) {
            User user = users.get(i);
            if (user.username.equals(username)) {
                return user;
            }
        }
        return guest();
    }

    /**
     * 判断注册是否成功
     *
     * @param username
     * @param password
     * @return
     */
    public static boolean register(String username, String password) {
        String salt = UUID.randomUUID().toString();
        String saltedPassword = ServiceAuth.SaltedPasswordHash(password, salt);
        try {
            // 将 session 存入数据库
            String sql = "INSERT INTO `blog`.`user` (username, password, role, salt) VALUES (?, ?, ?, ?)";
            MySQLStorage.update(sql, statement -> {
                // statement.setInt(1, id);
                statement.setString(1, username);
                statement.setString(2, saltedPassword);
                statement.setString(3, String.valueOf(UserRole.normal));
                statement.setString(4, salt);
            });
            return true;
        } catch (RuntimeException e) {
            Route.log("注册异常了");
            return false;
        }
    }

    /**
     * 修改密码
     * @param username
     * @param newPassword
     * @return
     */
    public static String updatePassword(String username, String newPassword) {
        // 拿到所有数据
        String sql = "SELECT * FROM `blog`.`user`";
        ArrayList<User> users = MySQLStorage.select(
                sql,
                resultSet -> {
                    int id = resultSet.getInt("id");
                    String usernameSql = resultSet.getString("username");
                    String passwordSql = resultSet.getString("password");
                    String role = resultSet.getString("role");
                    String salt = resultSet.getString("salt");
                    return new User(id, usernameSql, passwordSql, UserRole.valueOf(role), salt);
                }
        );
        // 更新 username 所对应的 password
        for (int i = 0; i < users.size(); i++) {
            User user = users.get(i);
            if (user.getUsername().equals(username)) {
                String salt = UUID.randomUUID().toString();
                String saltedPassword = SaltedPasswordHash(newPassword, salt);
                String sql1 = "UPDATE user SET password = ?, salt = ? WHERE username = ?";
                MySQLStorage.update(sql1, statement -> {
                    statement.setString(1, saltedPassword);
                    statement.setString(2, salt);
                    statement.setString(3, username);
                });
                HashMap<String, String> data = new HashMap<>();
                data.put("message", "密码修改成功！");
                String body = NewTemplate.render(data, "updatePassword.ftlh");
                return Route.responseHTML(body);
            }
        }
        return Route.route404();
    }

    /**
     * 删除session，退出登录
     * @param username
     */
    public static void exit(String username) {
        String sql = "DELETE FROM `blog`.`session` WHERE username = ?";
        MySQLStorage.update(sql, statement -> {
            statement.setString(1, username);
        });
    }
}
